// file:lib\string.c
// autor:jiang xinpeng
// time:2020.12.21
// copyright:(C) 2020-2050 by jiang xinpeng,All right are reserved.

#include <lib/string.h>
#include <os/memcache.h>
#include <lib/type.h>
#include <lib/stddef.h>

int strcmp(const char *src, const char *targe)
{
    char *s = (char *)src, *t = (char *)targe;

    if (!s || !t)
        return -1;

    // cmp two string while any string current char no equal '\0'
    for(;*s==*t;s++,t++)
    {
        if(!*s)
            break;
    }
    return (*s - *t); // >0 uper  =0 equal  <0 lower
}

char *strcat(char *targe, const char *src)
{
    int i, j;
    char *t = (char *)targe;
    char *s = (char *)src;

    // go to targe string end
    while (*t != '\0')
    {
        t++;
    }
    // copy src to targe end
    while (*s != '\0')
    {
        *t++ = *s++;
    }
    *t = '\0'; // write string eof flags
    return targe;
}

char *strstr(const char *src, const char *match)
{
    int i=0, j=0; // I control src pos,j control targe

    while (*(src + i) != '\0' && *(src + j) != '\0')
    {
        // equal next char
        if (*(src + i) == *(match + i))
        {
            i++;
            j++;
        }
        // if other char no equal
        else
        {
            i = i - j + 1; // src back to times current cmp start char+1
            j = 0;         // from sub string start char restart cmp
        }
    }
    // if is targe str has full cmp finish
    if (*(src + j) == '\0')
        return (char *)(src + (i - j));
}

char *strcpy(char *targe, const char *src)
{
    char *s = (char *)src;
    char *t = targe;

    while (*s != '\0')
    {
        *t++ = *s++;
    }
    *t = '\0';
    return s;
}

const char *strchr(const char *src, int ch)
{
    char *s = (char *)src;

    if (!s)
        return NULL;

    while (*s != '\0')
    {
        if (*s == ch)
            return s;
        s++;
    }
    return NULL;
}

const char *strrchr(const char *str, int c)
{
    char *ret;
    char *s = (char *)str;

    while (*s)
    {
        if (*s == c)
        {
            ret = s;
        }
        s++;
    }
    if (c == *s)
        ret = s;
    return ret;
}

int strlen(const char *str)
{
    uint32_t len = 0;
    char *s = (char *)str;

    while (*s++ != '\0')
    {
        ++len;
    }
    return len;
}

char *strncat(char *dst, const char *src, int n)
{
    char *d = dst;
    char *s = (char *)src;

    while (*d != '\0')
        d++;

    while (n && *d != '\0' && *s != '\0')
    {
        *d++ = *s++;
        n--;
    }
}

char *strncpy(char *_dst, const char *_src, int n)
{
    char *s = (char *)_src;
    char *r = _dst;

    while (n > 0&&*s)
    {
        *r++ = *s++;
        n--;
    }
    *r='\0';
}

int strncmp(const char *s1, const char *s2, int n)
{
    if (!n)
        return 0;

    while (n-- && *s1 && (*s1 == *s2))
    {
        s1++;
        s2++;
    }
    if (n > 0)
        return (int)(*s1 - *s2);
    else
        return 0;
}

void *memset(void *src, uint8_t value, uint32_t size)
{
    uint8_t *buff = src;
    int i = 0;

    while (i < size)
    {
        *(buff + i) = value;
        i++;
    }

    return src;
}

void *memcpy(void *targe, const void *src, uint32_t size)
{
    uint8_t *_targe = targe, *_src = (char *)src;

    while (size-- > 0)
    {
        *_targe++ = *_src++;
    }
    return _targe;
}

int memcmp(const void *src, const void *targe, uint32_t len)
{
    int i;
    uint8_t *src_t = (char *)src, *targe_t = (char *)targe;

    // len check
    for (i = 0; i < len; i++, targe_t++, src_t++)
    {
        if (*src_t - *targe_t > 0)
            return 1;
        else if (*src_t - *targe_t < 0)
            return -1;
    }
    return 0;
}

void string_init(string_t *string)
{
    string->len = 0;
    string->max_len = STRING_LEN_MAX;
    string->text = NULL;
}

int string_new(string_t *string, const char *text, uint32_t maxlen)
{
    if (!string || !text || !maxlen)
        return -1;

    string->text = (uint8_t *)KMemAlloc(maxlen);
    if (!string->text)
        return -1;

    // check and reset string maxlen
    if (maxlen >= STRING_LEN_MAX)
        maxlen = STRING_LEN_MAX - 1;
    string->max_len = maxlen;
    memset(string->text, 0, string->max_len);

    // figure and set string len
    // len max is string max len
    string->len = strlen(text);
    if (string->len > maxlen)
        string->len = maxlen;

    memcpy(string->text, text, string->len);
    string->text[string->len] = '\0';
    return 0;
}

void string_del(string_t *string)
{
    if (string->text)
    {
        KMemFree(string->text);
        string->text = NULL;
    }
    string->len = 0;
    string->max_len = STRING_LEN_MAX;
}

void string_empty(string_t *string)
{
    memset(string->text, 0, string->max_len);
}

void string_copy(string_t *string, char *text)
{
    string->len = strlen(text);

    if (string->len > string->max_len)
        string->len = string->max_len;
    memcpy(string->text, text, string->len);
    string->text[string->len] = '\0';
}
